/* 1
var person = (function() {
	var age = 40;
	function getAge() {
		return age;
	}
	function growOlder() {
		age++;
	}
	return {
		name: "Gump Yang",
		getAge: getAge,
		growOlder: growOlder
	};
}());

console.log(person.name);
console.log(person.getAge());

person.age = 100;
console.log(person.getAge());

person.growOlder();
console.log(person.getAge());
 */
/* 2
function Person(name) {
	var age = 40;
	this.name = name;

	this.getAge = function() {
		return age;
	}
	this.growOlder = function() {
		age++;
	}
};

var person = new Person("Gump Yang");

console.log(person.name);
console.log(person.getAge());

person.age = 100;
console.log(person.getAge());

person.growOlder();
console.log(person.getAge());
 */
/* 3
var Person =(function () {
	var age = 40;

	function InnerPerson(name) {
		this.name = name;
	}

	InnerPerson.prototype.getAge = function() {
		return age;
	};
	InnerPerson.prototype.growOlder = function() {
		age++;
	};

	return InnerPerson;
}());

var person1 = new Person("Gump Yang");
var person2 = new Person("Cheng");

console.log(person1.name);
console.log(person1.getAge());

console.log(person2.name);
console.log(person2.getAge());

person1.growOlder();
console.log(person1.getAge());
console.log(person2.getAge());
 */
/* 4
function EventTarget() {
}

EventTarget.prototype = {
	constructor: EventTarget,
	addListener: function(type, listener) {
		// create an array if it doesn't exist
		if(!this.hasOwnProperty("_listeners")) {
			this._listeners = [];
		}

		if (typeof this._listeners[type] == "undefined") {
			this._listeners[type] = [];
		}

		this._listeners[type].push(listener);
	},

	fire: function(event) {
		if (!event.target) {
			event.target = this;
		}

		if (!event.type) { // false
			throw new Error("Event object missing 'type' property.");
		}

		if (this._listeners&&this._listeners[event.type] instanceof Array) {
			var listeners = this._listeners[event.type];
			for (var i=0, len=listeners.length; i<len; i++) {
				listeners[i].call(this, event);
			}
		}
	},

	removeListener: function(type, listener) {
		if (this._listeners&&this._listeners[type] instanceof Array) {
			var listeners = this._listeners[type];
			for (var i=0, len=listeners.length; i<len; i++) {
				if (listeners[i] === listener) {
					listeners.splice(i, 1);
					break;
				}
			}
		}
	}
};

var target = new EventTarget();
target.addListener("message", function(event) {
	console.log("Message is " + event.data);
})

target.fire({
	type: "message",
	data: "Hello world!"
});

function Person(name) {
	this.name = name;
}

Person.prototype = Object.create(EventTarget.prototype);
Person.prototype.constructor = Person;

Person.prototype.sayName = function() {
	console.log(this.name);
	this.fire({type: "namesaid", name: name });
};

var person = new Person("Gump Yang");

console.log(person instanceof Person);
console.log(person instanceof EventTarget);
 */
/* 5
 */
function EventTarget() {
}

EventTarget.prototype = {
	constructor: EventTarget,
	addListener: function(type, listener) {
		// create an array if it doesn't exist
		if(!this.hasOwnProperty("_listeners")) {
			this._listeners = [];
		}

		if (typeof this._listeners[type] == "undefined") {
			this._listeners[type] = [];
		}

		this._listeners[type].push(listener);
	},

	fire: function(event) {
		if (!event.target) {
			event.target = this;
		}

		if (!event.type) { // false
			throw new Error("Event object missing 'type' property.");
		}

		if (this._listeners&&this._listeners[event.type] instanceof Array) {
			var listeners = this._listeners[event.type];
			for (var i=0, len=listeners.length; i<len; i++) {
				listeners[i].call(this, event);
			}
		}
	},

	removeListener: function(type, listener) {
		if (this._listeners&&this._listeners[type] instanceof Array) {
			var listeners = this._listeners[type];
			for (var i=0, len=listeners.length; i<len; i++) {
				if (listeners[i] === listener) {
					listeners.splice(i, 1);
					break;
				}
			}
		}
	}
};

function mixin(receiver, supplier) {
	for(var property in supplier) {
		if (supplier.hasOwnProperty(property)) {
			receiver[property] = supplier[property];
		}
	}
	return receiver;
}

var target = new EventTarget();
target.addListener("message", function(event) {
	console.log("Message is " + event.data);
})

target.fire({
	type: "message",
	data: "Hello world!"
});

function Person(name) {
	this.name = name;
}

mixin(Person.prototype, new EventTarget());
mixin(Person.prototype, {
	constructor: Person,
	sayName: function() {
		console.log(this.name);
		this.fire({type: "namesaid", name: name });
	}
});

var person = new Person("Gump Yang");

console.log(person instanceof Person);
console.log(person instanceof EventTarget);
